#include <console.h>
#include <device.h>
#include <errno.h>
#include <config.h>
#include <init.h>

static int uart_console_open(struct device *dev)
{
	struct console *con = device_to_console(dev);
	
	dev_flags_set_no_closing_flush(dev->flags); 
	return device_open(con->real_dev, dev->oflags);
}

static void uart_console_close(struct device *dev)
{
	struct console *con = device_to_console(dev);
	
	device_close(con->real_dev);
}

static int uart_console_read(struct device *dev, void *buf, unsigned int len)
{
	struct console *con = device_to_console(dev);
	
	return device_read(con->real_dev, buf, len);
}

static int uart_console_write(struct device *dev, const void *buf, unsigned int len)
{
	struct console *con = device_to_console(dev);

	return device_write(con->real_dev, buf, len);
}

static loff_t no_llseek(struct device *dev, loff_t offset, unsigned int origin)
{
	return -ENOTSUPP;
}

static int no_ioctl(struct device *dev, unsigned int cmd, unsigned int arg)
{
	return -ENOTSUPP;	
}

static void uart_console_flush(struct device *dev)
{
	struct console *con = device_to_console(dev);
	
	device_flush(con->real_dev);
}

static int uart_console_probe(struct device *dev, struct driver *drv)
{
	struct console *con = device_to_console(dev);
	struct device *real_dev;
	
	real_dev = device_lookup_by_name(CONFIG_CONSOLE_REAL_DEVICE_NAME);
	if (IS_ERR(real_dev)) 
		return PTR_ERR(real_dev);
	con->real_dev = real_dev;
	return 0;
}

struct device_operations console_ops = {
	.open	= uart_console_open,
	.close	= uart_console_close,
	.read	= uart_console_read,
	.write	= uart_console_write,
	.seek	= no_llseek,
	.ioctl	= no_ioctl,
	.flush	= uart_console_flush,
	.probe	= uart_console_probe,
};

static struct console uart_console_console;

DEVICE(uart_console_device, "uart_console", MKDEV(MAJOR_CONSOLE, 0), 
	DEV_FLAGS_CAN_READ | DEV_FLAGS_CAN_WRITE | DEV_FLAGS_CAN_NONBLOCK | DEV_FLAGS_CAN_SYNC, 
	&uart_console_console);

static struct console uart_console_console = {
	.dev = &uart_console_device,
};

static struct console_driver uart_console_console_driver;

DRIVER(uart_console_driver, NULL, MKDEV(MAJOR_CONSOLE, 0), MKDEV(MAJOR_CONSOLE, 0), 
	&console_ops, &uart_console_console_driver);

static struct console_driver uart_console_console_driver = {
	.drv = &uart_console_driver,
};

static int uart_console_init(void)
{
	console_register(&uart_console_console);
	return console_enable(&uart_console_console);	
}
core0_initcall(uart_console_init);

